import Input from '@/components/Input';
import NavBar from '@/components/NavBar';
import styles from './index.module.scss';
import { useFormik } from 'formik';
import * as Yup from 'yup';
import { useDispatch } from 'react-redux';
import { Toast } from 'antd-mobile';
import { sendCodes, Authorizations } from '@/store/action/login';
import { useEffect, useRef, useState } from 'react';
import { useHistory } from 'react-router-dom';

export default function Login() {
  const history = useHistory();
  // formik 库中提供的Hooks函数创建 formik 表单对象
  const formik = useFormik({
    // initialValues 返回一个 values    是表单的默认数据
    initialValues: {
      mobile: '15905139999',
      code: '123456',
    },
    // 表单提交事件处理函数，它接收表单数据作为参数
    // 这里的values拿到上面的两个属性
    onSubmit: async (values) => {
      // 获取token
      await dispatch(Authorizations(values));
      // 提示信息
      Toast.show({ content: '登录成功' });
      // 跳转到首页
      history.push('/');
    },

    /*
      // validate 是useFormik 提供的函数。进行校验
      // useFormik 可以配置表单验证方式 validate。
      // validate 是一个函数，接收表单数据作为参数。
      validate(values) {
        // 添加 TS 格式断言
        // useFormik 返回的对象包含 errors，就是验证方法返回的结果。
        const errors = {} as FormValues;
        // test() 方法用于检测一个字符串是否匹配某个模式
        if (!/^1[3-9]\d{9}$/.test(values.mobile)) {
          errors.mobile = '手机号格式错误';
        }
        if (!/^\d{6}$/.test(values.code)) {
          errors.code = '验证码格式错误';
        }
        return errors;
      },
    */

    // Yup 表单校验
    validationSchema: Yup.object().shape({
      // 手机号校验
      mobile: Yup.string()
        .required('手机号不能为空')
        .matches(/^1[3-9]\d{9}$/, '手机号格式错误'),
      // 验证码校验
      code: Yup.string()
        .required('验证码不能为空')
        .matches(/^\d{6}$/, '验证码格式错误'),
    }),
  });

  // 发送验证码
  const dispatch = useDispatch();
  const [time, setTime] = useState(0);
  const timerId = useRef(-1);
  const handleSendCodes = async () => {
    if (time > 0) return;
    // 校验错误
    if (formik.errors.mobile)
      return Toast.show({ content: formik.errors.mobile });
    // 调用发送验证码
    await dispatch(sendCodes(formik.values.mobile));
    // 发送验证码成功的提示
    Toast.show({ content: '获取验证码成功', duration: 1000 });
    // 开启倒计时
    setTime(60);
    /**
     * 定时器的两个注意点
     *    1. 定时器内部状态无法更新
     *    2. 组件卸载没有清理定时器
     */
    timerId.current = window.setInterval(() => {
      // 当我们每次都想要获取到最新的状态，需要写成，箭头函数的形式
      // setStae 是异步的，使用setStae(()=>)
      setTime((time) => {
        if (time === 1) clearInterval(timerId.current);
        return time - 1;
      });
    }, 1000);
  };
  // 清除定时器
  useEffect(() => {
    // 清理函数
    return () => {
      //  2. 组件卸载没有清理定时器,避免内存泄漏
      clearInterval(timerId.current);
    };
  }, []);

  return (
    <div className={styles.root}>
      <NavBar>登录</NavBar>
      <div className="content">
        {/* 标题 */}
        <h3>短信登录</h3>
        <form onSubmit={formik.handleSubmit}>
          {/* 手机号输入框 */}
          <div className="input-item">
            <Input
              autoFocus
              className="input"
              placeholder="请输入手机号"
              autoComplete="off"
              type="text"
              name="mobile"
              // 规定允许输入字段的最长度
              maxLength={11}
              // errormsg  输入内容不能通过验证时的提示信息
              errorMsg={formik.touched.mobile ? formik.errors.mobile : ''}
              // 在表单失去焦点的时候会触发验证的函数
              onBlur={formik.handleBlur}
              value={formik.values.mobile}
              onChange={formik.handleChange}
            />
          </div>

          {/* 短信验证码输入框 */}
          <div className="input-item">
            <Input
              className="input"
              placeholder="请输入验证码"
              autoComplete="off"
              type="text"
              name="code"
              maxLength={6}
              errorMsg={formik.touched.code ? formik.errors.code : ''}
              onBlur={formik.handleBlur}
              extra={
                <span onClick={() => handleSendCodes()}>
                  {time === 0 ? '获取验证码' : `${time}秒后重试`}
                </span>
              }
              value={formik.values.code}
              onChange={formik.handleChange}
            />
          </div>

          {/* 登录按钮 */}
          <button
            type="submit"
            className="login-btn"
            disabled={!formik.isValid}
          >
            登录
          </button>
        </form>
      </div>
    </div>
  );
}
